﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using System.Text;
using AChance.Dal.Entity;
using AChance.Func;

namespace AChance.Dal.Func
{
    public static class DalEntity
    {
        #region 获取类型
        /// <summary>
        /// 获取类型(根据名称)
        /// </summary>
        public static Type GetType(string name)
        {
            try
            {
                return Assembly.GetExecutingAssembly().GetType($"{typeof(FDWORG).Namespace}.{name}");
            }
            catch
            {
                return null;
            }
        }
        /// <summary>
        /// 获取类型(根据主键)
        /// </summary>
        public static Type GetTypeByKey(string key)
        {
            try
            {
                return GetType(GetNameByKey(key));
            }
            catch
            {
                return null;
            }
        }
        #endregion

        #region 获取名称
        /// <summary>
        /// 获取名称(根据类型)
        /// </summary>
        public static string GetName<T>() where T : class
        {
            return GetName(typeof(T));
        }
        /// <summary>
        /// 获取名称(根据类型)
        /// </summary>
        public static string GetName(Type type)
        {
            try
            {
                return type.GetType().Name;
            }
            catch
            {
                return string.Empty;
            }
        }
        /// <summary>
        /// 获取名称(根据字段名称)
        /// </summary>
        public static string GetName(string fieldName)
        {
            try
            {
                return nameof(FDWORG).Substring(0, 3) + fieldName.Substring(0, 3);
            }
            catch
            {
                return string.Empty;
            }
        }
        /// <summary>
        /// 获取名称(根据主键)
        /// </summary>
        public static string GetNameByKey(string key)
        {
            try
            {
                return nameof(FDWORG).Substring(0, 3) + key.Substring(10, 3);
            }
            catch
            {
                return string.Empty;
            }
        }
        #endregion

        #region 获取显示名称
        /// <summary>
        /// 获取显示名称(根据类型)
        /// </summary>
        public static string GetDispName<T>() where T : class
        {
            return GetDispName(typeof(T));
        }
        /// <summary>
        /// 获取显示名称(根据类型)
        /// </summary>
        public static string GetDispName(Type type)
        {
            try
            {
                var attr = (DisplayAttribute)type.GetCustomAttribute(typeof(DisplayAttribute));
                return attr?.Name ?? throw new Exception();
            }
            catch
            {
                return string.Empty;
            }
        }
        /// <summary>
        /// 获取显示名称(根据名称)
        /// </summary>
        public static string GetDispName(string name)
        {
            return GetDispName(GetType(name));
        }
        /// <summary>
        /// 获取显示名称(根据主键)
        /// </summary>
        public static string GetDispNameByKey(string key)
        {
            return GetDispName(GetTypeByKey(key));
        }
        /// <summary>
        /// 获取字段显示名称(根据字段名称)
        /// </summary>
        public static string GetFieldDispName(string fieldName)
        {
            try
            {
                var attr = (DisplayAttribute)GetType(GetName(fieldName)).GetProperty(fieldName).GetCustomAttribute(typeof(DisplayAttribute));
                return attr?.Name ?? throw new Exception();
            }
            catch
            {
                return string.Empty;
            }
        }
        #endregion

        #region 获取默认值
        /// <summary>
        /// 获取字段默认值(根据字段类型)
        /// </summary>
        public static object GetFieldDefault(Type fieldType)
        {
            try
            {
                object value;
                if (fieldType == typeof(string))
                    value = string.Empty;
                else if (fieldType == typeof(int)
                           || fieldType == typeof(int?)
                           || fieldType == typeof(double)
                           || fieldType == typeof(double?))
                    value = 0;
                else if (fieldType == typeof(byte[]))
                    value = new byte[] { };
                else if (fieldType.IsEnum)
                    value = Enum.ToObject(fieldType, 0);
                else if (fieldType.IsNullableEnum())
                    value = Enum.ToObject(Nullable.GetUnderlyingType(fieldType), 0);
                else
                    throw new Exception();
                return value;
            }
            catch
            {
                return null;
            }
        }
        #endregion

        #region 赋值操作
        /// <summary>
        /// 把实体中的所有字段都设置为null
        /// </summary>
        public static void Clear<T>(T entity)
        {
            if (entity is null)
                return;
            foreach (PropertyInfo propertyInfo in typeof(T).GetProperties())
            {
                try
                {
                    propertyInfo.SetValue(entity, null, null);
                }
                catch { }
            }
        }
        /// <summary>
        /// 把实体集合中的所有字段都设置为null
        /// </summary>
        public static void ClearRange<T>(List<T> entities)
        {
            if (entities.IsNullOrEmpty())
                return;
            entities.ForEach(entity => Clear(entity));
        }
        /// <summary>
        /// 把实体中的所有字段都设置为默认值
        /// </summary>
        public static void InitDefault<T>(T entity)
        {
            if (entity is null)
                return;
            foreach (PropertyInfo propertyInfo in typeof(T).GetProperties())
            {
                try
                {
                    propertyInfo.SetValue(entity, GetFieldDefault(propertyInfo.PropertyType), null);
                }
                catch { }
            }
        }
        /// <summary>
        /// 把实体集合中的所有字段都设置为默认值
        /// </summary>
        public static void InitDefaultRange<T>(List<T> entities)
        {
            if (entities.IsNullOrEmpty())
                return;
            entities.ForEach(entity => InitDefault(entity));
        }
        /// <summary>
        /// 把实体中的所有值为null的字段都设置为默认值
        /// </summary>
        public static void RepairDefault<T>(T entity)
        {
            if (entity is null)
                return;
            foreach (PropertyInfo propertyInfo in typeof(T).GetProperties())
            {
                try
                {
                    if (propertyInfo.GetValue(entity) is null)
                        propertyInfo.SetValue(entity, GetFieldDefault(propertyInfo.PropertyType), null);
                }
                catch { }
            }
        }
        /// <summary>
        /// 把实体集合中的所有值为null的字段都设置为默认值
        /// </summary>
        public static void RepairDefaultRange<T>(List<T> entities)
        {
            if (entities.IsNullOrEmpty())
                return;
            entities.ForEach(entity => RepairDefault(entity));
        }
        #endregion

        #region 获取Sql
        /// <summary>
        /// 获取实体对应的判断条件Sql
        /// </summary>
        public static string GetWhereSql<T>(T entity)
        {
            string where = "1 = 1";
            if (entity != null)
                foreach (PropertyInfo propertyInfo in typeof(T).GetProperties())
                {
                    try
                    {
                        object value = propertyInfo.GetValue(entity);
                        if (value is null)
                            continue;
                        else if (propertyInfo.PropertyType == typeof(string))
                            where += $" AND {propertyInfo.Name} = {value.ToString().ToSqlArg()}";
                        else if (propertyInfo.PropertyType == typeof(int)
                                   || propertyInfo.PropertyType == typeof(int?)
                                   || propertyInfo.PropertyType == typeof(double)
                                   || propertyInfo.PropertyType == typeof(double?))
                            where += $" AND {propertyInfo.Name} = {value}";
                        else if (propertyInfo.PropertyType.IsEnum
                                   || propertyInfo.PropertyType.IsNullableEnum())
                            where += $" AND {propertyInfo.Name} = {(int)value}";
                    }
                    catch { }
                }
            return $" ({where}) ";
        }
        #endregion


    }
}
